package com.lft.cryptology05.desaes;

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class DesDemo {
    public static void main(String[] args) throws Exception {
        // 明文
        String input = "中国";
        System.out.println("加密之前的明文为: " + input);
        
        // DES 加密必须是8位。
        String key = "12345678";
        
        // 算法
        String algorithm = "DES";
        
        String transformation = "DES";
        
        // 加密
        String encryptDes = encryptDes(input, key, algorithm, transformation);
        // 打印密文
        System.out.println("加密之后密文为: " + encryptDes);
        
        String decryptDes = decryptDes(encryptDes, key, algorithm, transformation);
        System.out.println("解密之后的明文为: " + decryptDes);
        
    }
    
    /**
     * 使用 DES 加密
     * @param input          明文
     * @param key            密钥（DES，密钥长度必须是8个字节）
     * @param algorithm      获取 Cipher 对象的算法
     * @param transformation 获取密钥的算法
     * @return 密文
     */
    private static String encryptDes(String input, String key, String algorithm, String transformation) throws Exception {
        // Cipher：密码，获取加密对象
        // transformation：参数表示使用什么类型加密
        Cipher cipher = Cipher.getInstance(transformation);
        
        // 指定密钥规则
        // 第一个参数表示：密钥，key 的字节数组
        // 第二个参数表示：算法
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        
        // 对加密进行初始化
        // 第一个参数表示：模式，有加密模式和解密模式
        // 第二个参数表示：密钥规则
        cipher.init(Cipher.ENCRYPT_MODE, sks);
        
        // 进行加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        
        // 打印字节，因为 ascii 码有负数，解析不出来，所以乱码。
        // 对数据进行 Base64 编码
        String encode = Base64.encode(bytes);
        
        return encode;
    }
    
    private static String decryptDes(String input, String key, String algorithm, String transformation) throws Exception {
        
        // 获取 Cipher 对象
        Cipher cipher = Cipher.getInstance(transformation);
        
        // 指定密钥规则
        SecretKeySpec sks = new SecretKeySpec(key.getBytes(), algorithm);
        
        // 初始化 Cipher
        cipher.init(Cipher.DECRYPT_MODE, sks);
        
        // 解密
        byte[] bytes = cipher.doFinal(Base64.decode(input));
        // 解密之后的就是明文。直接返回
        return new String(bytes);
    }
    
}
